import os
import random
import subprocess
import time
import traceback

import numpy
import requests
from loguru import logger
from playwright.sync_api import sync_playwright

class Login:
    def __init__(self, playwright, host, command):
        self.playwright = playwright
        self.host = host
        self.command = command
        self.context = None
        self.browser = None
        self.page = None
        self.index_url = "https://web.txcs.tmall.com/login"
        self.user_name = "18938939905"
        self.pwd = "xtcs135246"

    def login(self):
        try:
            os.system('taskkill /F /IM chrome.exe')
            time.sleep(3)
            logger.info("浏览器路径：{}".format(self.command))
            subprocess.Popen(self.command)
            time.sleep(5)
            chromium = self.playwright.chromium.connect_over_cdp(r"http://localhost:9001")
            context = chromium.new_context(accept_downloads=True)
            self.page = context.new_page()
            self.page.goto(self.index_url, timeout=20000)
            self.wait(self.page)
            # 先调用一下，否则可能会找不到
            frame = self.page.frame(url='https://havanalogin.taobao.com/mini_login.htm*')
            # 输入账号
            frame.fill('//*[@id="fm-login-id"]', self.user_name)
            time.sleep(2)
            # 输入密码
            frame.fill('//*[@id="fm-login-password"]', self.pwd)
            time.sleep(5)
            logger.info("检查元素...")
            # 检查是否出现滑动验证码
            self.page.query_selector('div.river-origin-frame')
            logger.info("query_selector")
            baxia_frame = self.page.frame(name='baxia-dialog-content')
            logger.info("检查是否正常打开页面...")
            for i in range(5):
                try:
                    if baxia_frame is not None:
                        if baxia_frame.query_selector('//*[@id="nc_1_n1z"]') is not None and baxia_frame.query_selector(
                                '//*[@id="nc_1_n1z"]').is_visible():
                            logger.info("出现滑动验证码，开始滑动...")
                            for k in range(20):
                                err_loading = baxia_frame.query_selector('div.errloading')
                                if err_loading is not None:
                                    baxia_frame.query_selector('div.errloading').click()
                                    time.sleep(1)
                                    logger.info("出现验证码错误，点击【刷新】按钮...")
                                    box = baxia_frame.query_selector('//*[@id="nc_1_n1z"]').bounding_box()
                                    track = self.get_tracks(280, 1, self.ease_out_quart)
                                    ix = int(box['x'] + box['width'] // 2)
                                    iy = int(box['y'] + box['height'] // 2)
                                    self.page.mouse.move(ix, iy)
                                    self.page.mouse.down(button='left')
                                    self.move_to_gap(self.page, ix, iy, track)
                                    time.sleep(1.5)
                                    logger.info("滑动完成...")
                                else:
                                    self.page.query_selector('div.river-origin-frame')
                                    if baxia_frame.query_selector('//*[@id="nc_1_n1z"]') is None:
                                        break
                                    box = baxia_frame.query_selector('//*[@id="nc_1_n1z"]').bounding_box()
                                    track = self.get_tracks(280, 1, self.ease_out_quart)
                                    ix = int(box['x'] + box['width'] // 2)
                                    iy = int(box['y'] + box['height'] // 2)
                                    self.page.mouse.move(ix, iy)
                                    self.page.mouse.down(button='left')
                                    self.move_to_gap(self.page, ix, iy, track)
                                    time.sleep(1.5)
                                    logger.info("滑动完成...")
                                time.sleep(2)
                            break
                    else:
                        time.sleep(1)
                        logger.info("没有找到frame...")
                        self.page.query_selector('div.river-origin-frame')
                        baxia_frame = self.page.frame(name='baxia-dialog-content')
                except Exception as e:
                    logger.error(e)
                time.sleep(0.5)
            # 点击登录
            frame.query_selector('button:has-text("登录")').click()
            logger.info("点击【登录】按钮...")
            self.wait(frame)
            time.sleep(1)
            # 先调用一下，否则可能会找不到
            frame.query_selector('button:has-text("登录")')
            self.wait(frame)
            frame = self.page.frame(url='https://web.txcs.tmall.com/pages/ascm/basic_login_proxy*')
            for i in range(20):
                if frame is None:
                    time.sleep(1)
                frame = self.page.frame(url='https://web.txcs.tmall.com/pages/ascm/basic_login_proxy*')
                if frame is not None:
                    break
            # 选择商家类型
            for i in range(20):
                if frame.query_selector('label:has-text("商品供应商")') is not None and frame.query_selector(
                        'label:has-text("商品供应商")').is_visible():
                    time.sleep(1)
                    break
                time.sleep(1)
            frame.query_selector('label:has-text("商品供应商")').click()
            logger.info("点击【商品供应商】按钮...")
            time.sleep(2)
            # 点开二级供应商
            frame.query_selector('div.next-form-item:has(label:has-text("二级供应商")) >> input').click()
            time.sleep(0.5)
            # 选择第一个
            frame.query_selector('ul >> li').click()
            time.sleep(0.5)
            # 点击进入商家
            frame.query_selector('button:has-text("进入商家")').click()
            logger.info("点击【进入商家】按钮...")
            self.wait(frame)
            self.close_dialog()
            logger.info('回到旧版')
            self.page.query_selector('div.header-right-item:has-text("回到旧版")').click()
            self.wait(self.page)
            self.close_dialog()
            time.sleep(1)
            return True
        except:
            logger.info(traceback.format_exc())
            return False

    def close_dialog(self):
        for i in range(20):
            try:
                if len(self.page.query_selector_all('a.next-dialog-close')) > 0:
                    close_button_list = self.page.query_selector_all('a.next-dialog-close')
                    for close_button in close_button_list:
                        if close_button.is_visible():
                            close_button.click()
                            break
                logger.info("正在等待页面检查完成【{}】【{}】", i, 20)
                time.sleep(1)
            except:
                pass
        for i in range(10):
            try:
                if self.page.query_selector('div.aes-survey-pop--close:visible') is not None:
                    self.page.query_selector('div.aes-survey-pop--close:visible').click(timeout=3000)
                    break
                time.sleep(1)
            except:
                pass
            time.sleep(1)
        for i in range(3):
            if len(self.page.query_selector_all('a.ascp-frame-dialog-close:visible')) > 0:
                for dialog in self.page.query_selector_all('a.ascp-frame-dialog-close:visible'):
                    try:
                        dialog.click(timeout=3000)
                    except:
                        pass

    def ease_out_quart(self, x):
        return 1 - pow(1 - x, 4)

    def get_tracks(self, distance, seconds, ease_func):
        distance += 0
        tracks = [0]
        offsets = [0]
        for t in numpy.arange(0.0, seconds, 0.1):
            ease = ease_func
            offset = round(ease(t / seconds) * distance)
            tracks.append(offset - offsets[-1])
            offsets.append(offset)
        tracks.extend([-3, -2, -3, -2, -2, -2, -2, -1, -0, -1, -1, -1])
        return tracks

    def move_to_gap(self, page, ix, iy, track):
        """
        慢速移动鼠标
        :param ix:
        :param iy:
        :param track:
        :return:
        """
        f_y = [10, 12, 4, 6, 8, -4, -6, -8]
        mx = ix
        while track:
            x = track.pop(0)
            mx = mx + x
            page.mouse.move(mx, iy + random.choice(f_y))
            time.sleep(0.1)
        page.mouse.up()

    def wait(self, page, seconds=1):
        page.wait_for_load_state(state="domcontentloaded")
        time.sleep(seconds)